package com.common.sdk.net.connect.fresco;

import android.util.Log;
import android.util.Pair;

import com.android.sohu.sdk.common.toolbox.LogUtils;
import com.facebook.common.logging.FLog;
import com.facebook.imagepipeline.listener.RequestLoggingListener;
import com.facebook.imagepipeline.request.ImageRequest;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by sangchengjiang on 16/8/10.
 */
public class CustomRequestLoggingListener extends RequestLoggingListener {

    private static final String TAG = "RequestLoggingListener";

    private final Map<Pair<String, String>, Long> mProducerStartTimeMap;
    private final Map<String, Long> mRequestStartTimeMap;

    public CustomRequestLoggingListener() {
        mProducerStartTimeMap = new HashMap<>();
        mRequestStartTimeMap = new HashMap<>();
    }

    @Override
    public synchronized void onRequestStart(
            ImageRequest request,
            Object callerContextObject,
            String requestId,
            boolean isPrefetch) {
        LogUtils.d(TAG, "time " + getTime() + ": onRequestSubmit: {requestId: " + requestId + ", callerContext: " + callerContextObject + ", isPrefetch: " + isPrefetch + "}");
        mRequestStartTimeMap.put(requestId, getTime());
    }

    @Override
    public synchronized void onProducerStart(String requestId, String producerName) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        long startTime = getTime();
        mProducerStartTimeMap.put(mapKey, startTime);
        LogUtils.d(TAG, "time " + startTime + ": onProducerStart: {requestId: " + requestId + ", producer: " + producerName + "}");
    }

    @Override
    public synchronized void onProducerFinishWithSuccess(
            String requestId,
            String producerName,
            Map<String, String> extraMap) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        Long startTime = mProducerStartTimeMap.remove(mapKey);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + getTime() + ": onProducerFinishWithSuccess: " +
                "{requestId: " + requestId + ", producer: " + producerName + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms, extraMap: " + extraMap + "}");
    }

    @Override
    public synchronized void onProducerFinishWithFailure(
            String requestId,
            String producerName,
            Throwable throwable,
            Map<String, String> extraMap) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        Long startTime = mProducerStartTimeMap.remove(mapKey);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + startTime + ": onProducerFinishWithFailure: " +
                "{requestId: " + requestId + ", stage: " + producerName + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms, extraMap: " + extraMap + ", throwable: " + throwable + "}");
        LogUtils.e(TAG, throwable.toString(), throwable);
    }

    @Override
    public synchronized void onProducerFinishWithCancellation(
            String requestId,
            String producerName,
            Map<String, String> extraMap) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        Long startTime = mProducerStartTimeMap.remove(mapKey);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + currentTime + ": onProducerFinishWithCancellation: " +
                "{requestId: " + requestId + ", stage: " +producerName + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms, extraMap: " + extraMap + "}");
    }

    @Override
    public synchronized void onProducerEvent(
            String requestId, String producerName, String producerEventName) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        Long startTime = mProducerStartTimeMap.get(mapKey);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + getTime() + ": onProducerEvent: {requestId: " + requestId + ", stage: " + producerName + ", eventName: " + producerEventName + "; elapsedTime: " +getElapsedTime(startTime, currentTime) + " ms}");

    }

    @Override
    public synchronized void onUltimateProducerReached(
            String requestId,
            String producerName,
            boolean successful) {
        Pair<String, String> mapKey = Pair.create(requestId, producerName);
        Long startTime = mProducerStartTimeMap.remove(mapKey);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + currentTime + ": onUltimateProducerReached: " +
                "{requestId: " + requestId + ", producer: " + producerName + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms, success: " + successful + "}");
    }

    @Override
    public synchronized void onRequestSuccess(
            ImageRequest request,
            String requestId,
        boolean isPrefetch) {
        Long startTime = mRequestStartTimeMap.remove(requestId);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + currentTime + ": onRequestSuccess: {requestId: " + requestId + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms}");
    }

    @Override
    public synchronized void onRequestFailure(
            ImageRequest request,
            String requestId,
            Throwable throwable,
        boolean isPrefetch) {
        Long startTime = mRequestStartTimeMap.remove(requestId);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + currentTime + ": onRequestFailure: {requestId: " + requestId + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms, throwable: " + throwable.toString() + "}");
        LogUtils.e(TAG, throwable.getMessage(), throwable);
    }

    @Override
    public synchronized void onRequestCancellation(String requestId) {
        Long startTime = mRequestStartTimeMap.remove(requestId);
        long currentTime = getTime();
        LogUtils.d(TAG, "time " + currentTime + ": onRequestCancellation: {requestId: " + requestId + ", elapsedTime: " + getElapsedTime(startTime, currentTime) + " ms}");
    }

    private static long getElapsedTime(Long startTime, long endTime) {
        if (startTime != null) {
            return endTime - startTime;
        }
        return -1;
    }

    private long getTime() {
        return System.currentTimeMillis();
    }
}
